/**
 * indexedDB 浏览器本地数据库管理文件 50.16.0.2406 版本首次引入
 * @param {String} dbName 数据库名称，默认值 "defaultCacheName"
 * @param {Number} dbVersion 数据库版本号，默认值 1
 * @param {String} dbStoreName 数据库存储空间名称，默认值 "commonLangStore"
 * @param {Object} dbTarget 数据库实例对象
 * @param {Object} dbStoreTarget 数据库存储空间的实例对象
 * @param {Function} initDataBase 数据库连接方法
 * @param {Function} addDataBaseData(data) 添加数据库数据方法，传入要入库的对象参数
 * @param {Function} getDataBaseData(dataId) 读取数据库数据方法，传入要读取的数据对象id
 * @param {Function} deleteDataBaseData(dataId) 删除数据库数据方法，传入要读取的数据对象id
 * @param {Function} closeDataBase 关闭数据库方法
 * 
 */
const dbm = {
    /** 数据库名称 */
    dbName: "defaultCacheName",
    /** 数据库版本号 */
    dbVersion: 1,
    /** 数据库存储空间名称 */
    dbStoreName: "commonLangStore",
    /** 数据库实例对象 */
    dbTarget: null,
    /** 数据库存储空间的实例对象 */
    dbStoreTarget: null,
    /** 数据库连接对象 */
    dbRequest: null,
    /** 
     * 初始化数据库
     **/
    initDataBase: () => {
        let self = dbm
        return new Promise((resolve, reject) => {
            let rejectMsg = ''
            if(!self.dbRequest) {
                let _indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB
                if(!_indexedDB) {
                    reject('indexedDB is not exist !')
                    return
                }
                // 创建或者说打开指定数据库
                self.dbRequest = _indexedDB.open(self.dbName, self.dbVersion);
                // 监听数据库连接成功事件
                self.dbRequest.onsuccess = function(event) {
                    const db = event.target.result;
                    self.dbTarget = db
                    // let resData = self.createDB(db)
                    // 进行数据库操作
                    resolve({'db': db})
                    // resolve(resData)
                };
                // 监听数据库升级事件
                self.dbRequest.onupgradeneeded = function(event) {
                    const db = event.target.result;
                    self.dbTarget = db
                    let resData = self.createDB(db)
                    resolve(resData)
                };
                // 监听数据库连接失败事件
                self.dbRequest.onerror = function(event) {
                    rejectMsg = `indexedDB 【onerror】：Failed to open database `
                    console.log(rejectMsg, event)
                    reject(rejectMsg)
                };
            } else {
                resolve({'db': self.dbTarget})
            }
        })
    },
    /**
     * 连接数据库
     */
    createDB: (db) => {
        let res = {}
        if(db) {
            let self = dbm
            // 创建对象存储空间(表)或修改数据库结构
            const store = db.createObjectStore(self.dbStoreName, { keyPath: 'id'}); // autoIncrement 是否允许索引 key 自增
            // 设置存储空间索引，索引名称是id，索引值要唯一
            store.createIndex('id', 'id', {'unique': false})
            console.log(`indexedDB database open successfullydb ：`, db)
            console.log(`indexedDB store ：`, store)
            res = {'db': db, 'store': store}
        }
        return res
    },
    /**
     * 添加数据库数据
     * @param {Object} data {id, data}, 例如：{ id: '1', data: 'example' }
     */
    addDataBaseData: (data) => {
        let self = dbm
        return new Promise((resolve, reject) => {
            let rejectMsg = ''
            if(!data || typeof data !== "object") {
                rejectMsg = `indexedDB 【add】data must be object! `
                console.error(rejectMsg)
                reject(rejectMsg)
                return
            }
            if(self.dbTarget) {
                // 先查询数据是否已经存在，存在则更新、不存在则添加
                self.getDataBaseData(data.id).then(res => {
                    if(res) {
                        self.eventHandler(data, 'put').then(res1 => {
                            resolve(res1)
                        }).catch(error => {
                            reject(error)
                        })
                    } else {
                        // 添加数据到数据库
                        self.eventHandler(data, 'add').then(res2 => {
                            resolve(res2)
                        }).catch(err => {
                            reject(err)
                        })
                    }
                }).catch(e => {
                    // 读取不到数据，则是数据不存在
                    // 添加数据到数据库
                    self.eventHandler(data, 'add').then(res3 => {
                        resolve(res3)
                    }).catch(err => {
                        reject(err)
                    })
                })
            } else {
                rejectMsg = `indexedDB 【add】db target is null! `
                console.error(rejectMsg)
                reject(rejectMsg)
            }
        })
    },
    /**
     * 读取数据库数据
     * @param {String} dataId 要读取的数据id
     */
    getDataBaseData: (dataId) => {
        let self = dbm
        return new Promise((resolve, reject) => {
            let rejectMsg = ''
            if(!dataId || typeof dataId !== "string") {
                rejectMsg = `indexedDB 【get】dataId must be string! `
                console.error(rejectMsg)
                reject(rejectMsg)
                return
            }
            if(self.dbTarget) {
                self.eventHandler(dataId, 'get').then(res => {
                    resolve(res)
                }).catch(err => {
                    reject(err)
                })
            } else {
                rejectMsg = `indexedDB 【add】db target is null`
                console.error(rejectMsg)
                reject(rejectMsg)
            }
        })
    },
    /**
     * 删除数据库数据
     * @param {String} dataId 要删除的数据id
     */
    deleteDataBaseData: (dataId) => {
        let self = dbm
        return new Promise((resolve, reject) => {
            let rejectMsg = ''
            if(!dataId || typeof dataId !== "string") {
                rejectMsg = `indexedDB 【delete】dataId must be string! `
                console.error(rejectMsg)
                reject(rejectMsg)
                return
            }
            if(self.dbTarget) {
                self.eventHandler(dataId, 'delete').then(res => {
                    resolve(res)
                }).catch(err => {
                    reject(err)
                })
            } else {
                rejectMsg = `indexedDB 【delete】db target is null`
                console.error(rejectMsg)
                reject(rejectMsg)
            }
        })
    },
    /**
     * 事件处理
     * @param data: 操作数据
     * @param eventType: 操作类型 'add' 新增、'put' 更新、'get' 读取
     */
    eventHandler: (data, eventType) => {
        let self = dbm
        return new Promise((resolve, reject) => {
            // 创建事务
            const transaction = self.dbTarget.transaction([self.dbStoreName], eventType === 'get' ? 'readonly' : 'readwrite');
                // 创建存储对象
            const _objectStore = transaction.objectStore(self.dbStoreName);
            const request = _objectStore[eventType](data);
            // 监听添加成功事件
            request.onsuccess = function(event) {
                // 处理添加操作成功
                let rejectMsg = `indexedDB 【onsuccess】：successfully to ${eventType} data! `
                console.log(rejectMsg)
                resolve(request.result)
            };
            // 监听添加失败事件
            request.onerror = function(event) {
                // 处理添加操作失败
                let rejectMsg = `indexedDB 【onerror】：Failed to ${eventType} data! `
                console.error(rejectMsg, event)
                reject(event)
            };
        })
    },
    /**
     * 关闭数据库连接
     */
    closeDataBase: () => {
        let self = dbm
        return new Promise((resolve, reject) => {
            if(self.dbTarget) {
                self.dbTarget.close()
                resolve()
            } else {
                let rejectMsg = `indexedDB 【close】db target is null`
                console.error(rejectMsg)
                reject(rejectMsg)
            }
        })
    }
}
export default dbm